﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using mshtml;   

namespace BookInfoExtractor
{
    public class BookPattern
    {
        private HtmlElement _author;
        private HtmlElement _title;
        private HtmlElement _image;
        private HtmlElement _isbn;
        private HtmlElement _price;

        private static int level = -1;
        //private static int posIndex = 0;
        private static string nodePosition = string.Empty;
        private List<int> lstTrackPos = new List<int>();
        private List<int> lstAuthorPos = new List<int>();
        private List<int> lstTitlePos = new List<int>();
        private List<int> lstImagePos = new List<int>();
        private List<int> lstISBNPos = new List<int>();
        private List<int> lstPricePos = new List<int>();

        private static bool isFound = false;

        public HtmlElement Element { get; set; }
        public string ClassNameToSearch { get; set; }

        public HtmlElement Author
        { 
            get
            {
                return _author;
            } 
            set
            {
                _author = value;
                lstTrackPos.Clear();
                isFound = false;
                SetHierarchicalPosition(Element, _author);
                lstAuthorPos = lstTrackPos.ToList();
                lstAuthorPos.Reverse();  
            } 
        }

        public HtmlElement Title
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value;
                lstTrackPos.Clear();
                isFound = false;
                SetHierarchicalPosition(Element, _title);
                lstTitlePos = lstTrackPos.ToList();
                lstTitlePos.Reverse();
            }
        }

        public HtmlElement Image
        {
            get
            {
                return _image;
            }
            set
            {
                _image = value;
                lstTrackPos.Clear();
                isFound = false;
                SetHierarchicalPosition(Element, _image, true);
                lstImagePos = lstTrackPos.ToList();
                lstImagePos.Reverse();
            }
        }
        public HtmlElement ISBN
        {
            get
            {
                return _isbn;
            }
            set
            {
                _isbn = value;
                lstTrackPos.Clear();
                isFound = false;
                SetHierarchicalPosition(Element, _isbn);
                lstISBNPos = lstTrackPos.ToList();
                lstISBNPos.Reverse();
            }
        }

        public HtmlElement Price
        {
            get
            {
                return _price;
            }
            set
            {
                _price = value;
                lstTrackPos.Clear();
                isFound = false;
                SetHierarchicalPosition(Element, _price);
                lstPricePos = lstTrackPos.ToList();
                lstPricePos.Reverse();
            }
        }

        public List<int> GetAuthorPosition()
        {
            return lstAuthorPos; 
        }

        public void SetAuthorPosition(string authorPosition, string[] delimiter)
        {
            lstAuthorPos.Clear();
            foreach(string position in authorPosition.Split(delimiter, StringSplitOptions.RemoveEmptyEntries))
            {
                if(position.Trim() != string.Empty)
                    lstAuthorPos.Add(int.Parse(position));
            }
        }

        public List<int> GetTitlePosition()
        {
            return lstTitlePos;
        }

        public void SetTitlePosition(string titlePosition, string[] delimiter)
        {
            lstTitlePos.Clear();
            foreach (string position in titlePosition.Split(delimiter, StringSplitOptions.RemoveEmptyEntries))
            {
                if (position.Trim() != string.Empty)
                    lstTitlePos.Add(int.Parse(position));
            }
        }

        public List<int> GetImagePosition()
        {
            return lstImagePos;
        }

        public void SetImagePosition(string imagePos, string[] delimiter)
        {
            lstImagePos.Clear();
            foreach (string position in imagePos.Split(delimiter, StringSplitOptions.RemoveEmptyEntries))
            {
                if (position.Trim() != string.Empty)
                    lstImagePos.Add(int.Parse(position));
            }
        }

        public List<int> GetISBNPosition()
        {
            return lstISBNPos;
        }

        public void SetISBNPosition(string isbnPos, string[] delimiter)
        {
            lstISBNPos.Clear();
            foreach (string position in isbnPos.Split(delimiter, StringSplitOptions.RemoveEmptyEntries))
            {
                if (position.Trim() != string.Empty)
                    lstISBNPos.Add(int.Parse(position));
            }
        }

        public List<int> GetPricePosition()
        {
            return lstPricePos;
        }

        public void SetPricePosition(string pricePosition, string[] delimiter)
        {
            lstPricePos.Clear();
            foreach (string position in pricePosition.Split(delimiter, StringSplitOptions.RemoveEmptyEntries))
            {
                if (position.Trim() != string.Empty)
                    lstPricePos.Add(int.Parse(position));
            }
        }

        public static HtmlElement TryMatch(HtmlDocument doc, string tagName, string id, string className)
        {
            foreach(HtmlElement node in doc.GetElementsByTagName(tagName))
            {
                //if (id != string.Empty && node.Id != id)
                //    continue;

                IHTMLElement domNode = node.DomElement as IHTMLElement;
                if (domNode.className == className)
                {
                    return node;
                }
            }
            return null;
        }

        //public static void Apply(HtmlElement patternElem, HtmlDocument doc, string classToSearch)
        //{
        //    foreach (HtmlElement obj in FindPattern(patternElem, doc, classToSearch))
        //    {

        //    }
        //}

        public static List<HtmlElement> ApplyPattern(HtmlElement patternElement, HtmlDocument document, string classToSearch)
        {
            IEnumerable<HtmlElement> collElements = document.GetElementsByTagName(patternElement.TagName).Cast<HtmlElement>();
            dynamic domElement = patternElement.DomElement;
            string elemClass = domElement.className;
            //IEnumerable<HtmlElement> matchedElements = collElements.Where(node => node.GetAttribute("class").StartsWith(element.GetAttribute("class")));
            List<HtmlElement> lstElements = new List<HtmlElement>();

            //objPattern.ClassNameToSearch = txtClass.Text;

            foreach (HtmlElement node in collElements)
            {
                dynamic nodeDomElement = node.DomElement;
                string nodeClassName = nodeDomElement.className;
                if (nodeClassName != null && nodeClassName.Contains(classToSearch))
                {
                    lstElements.Add(node);
                    node.Style = "background-color:yellow";
                }
            }

            return lstElements;
        }

        private void SetHierarchicalPosition(HtmlElement _subElement, HtmlElement _searchNode, bool isImg = false)
        {
            HtmlElement topNode;
            topNode = _subElement; 
            //if (level == 0)
            //    topNode = Element;
            //else
            //    topNode = _subElement;

            int posIndex = 0;
            foreach (HtmlElement child in topNode.Children)
            {
                if (isFound)
                    break;

                if (isImg)
                {
                    //child is image, then check if src matches
                    //if matched then found
                    //else recursive as below

                    if ((child.DomElement is IHTMLImgElement) && (((IHTMLImgElement)child.DomElement).src == ((IHTMLImgElement)_searchNode.DomElement).src))
                    {
                        nodePosition = nodePosition + posIndex + "-" + child.TagName + ".";
                        lstTrackPos.Add(posIndex);
                        MessageBox.Show(child.InnerText);
                        isFound = true;
                        break;
                    }
                    else
                    {
                        SetHierarchicalPosition(child, _searchNode, true);
                        if (isFound)
                        {
                            nodePosition = nodePosition + posIndex + "-" + child.TagName + ".";
                            lstTrackPos.Add(posIndex);
                        }
                    }

                }
                else
                {
                    if (child.InnerText != _searchNode.InnerText)
                    {
                        SetHierarchicalPosition(child, _searchNode);
                        if (isFound)
                        {
                            nodePosition = nodePosition + posIndex + "-" + child.TagName + ".";
                            lstTrackPos.Add(posIndex);
                        }
                    }
                    else
                    {
                        nodePosition = nodePosition + posIndex + "-" + child.TagName + ".";
                        lstTrackPos.Add(posIndex);
                        MessageBox.Show(child.InnerText);
                        isFound = true;
                        break;
                    }
                }
                posIndex++;
            }
        }

    }
}
